package com.cy.pj.sys.web.config;

import com.cy.pj.sys.service.realm.ShiroRealm;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.cache.MemoryConstrainedCacheManager;
import org.apache.shiro.mgt.RememberMeManager;
import org.apache.shiro.realm.Realm;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.spring.web.config.DefaultShiroFilterChainDefinition;
import org.apache.shiro.spring.web.config.ShiroFilterChainDefinition;
import org.apache.shiro.web.mgt.CookieRememberMeManager;
import org.apache.shiro.web.servlet.SimpleCookie;
import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class ShiroConfig {
    @Bean
    public SessionManager sessionManager(){
        DefaultWebSessionManager sessionManager= new DefaultWebSessionManager();
        //session 的超时时间
        sessionManager.setGlobalSessionTimeout(1000*60*60);//1 个小时
        //sessionManager.setGlobalSessionTimeout(2*60*1000);//2 分钟
        //删除无效 session
        sessionManager.setDeleteInvalidSessions(true);
        //当客户端 cookie 被禁用是否要设置 url 重写
        sessionManager.setSessionIdUrlRewritingEnabled(false);
        return sessionManager;
    }

    /**
     * 定义Realm对象，通过此对象访问数据库中的用户和权限信息，并进行封装。
     * @Bean 注解描述方法时，表示方法的返回要交给spring管理，这个bean的名字默认
     * 为方法名。,还可以自己起名，例如@Bean("shiroRealm")*/
    @Bean
    public Realm realm() {//org.apache.shiro.realm.Realm
        return new ShiroRealm();
    }

    /**
     * 基于此对象定义过滤规则，例如哪些请求必须要认证，哪些请求不需要认证
     * ShiroFilterChainDefinition 此对象中定义了若干过滤器Filter，基于这
     * 些过滤器以及我们定义的过滤规则对业务进行实现。
     */
    @Bean
    public ShiroFilterChainDefinition shiroFilterChainDefinition() {
        DefaultShiroFilterChainDefinition chainDefinition =
                new DefaultShiroFilterChainDefinition();
        //配置/user/login/**开头的资源，可以匿名访问(不用登录就可以访问),
        //其中 anon 为 shiro 框架指定的匿名过滤器
        chainDefinition.addPathDefinition("/user/login/**", "anon");
        //配置登出操作
        chainDefinition.addPathDefinition("/user/logout", "logout");
        //配置以/**开头的资源必须都要经过认证，
        //其中 authc 为 shiro 框架指定的认证过滤器
        chainDefinition.addPathDefinition("/**", "user");
        return chainDefinition;
    }

    /**
     * 如果@RequiresPermissions注解写在了控制层会导致登录不上，这个时候加上下面的bean标注的方法就可以解决问题
     * PS:如果控制层标注的是@Transactional注解也会出现登录不了的问题
     * @return
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator(){
        DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        advisorAutoProxyCreator.setUsePrefix(true);
        return advisorAutoProxyCreator;
    }

    /**
     * 设置浏览器记住我，退出浏览器后可以直接登录
     * @return
     */
    @Bean
    public RememberMeManager rememberMeManager(){
        CookieRememberMeManager rememberMeManager= new CookieRememberMeManager();
        SimpleCookie cookie=new SimpleCookie("rememberMe");
        cookie.setMaxAge(7*24*60*60);//7 天，默认 1 年
        rememberMeManager.setCookie(cookie);
        return rememberMeManager;
    }

    /**
     * 配置授权缓存管理器，默认应用的缓存是shiro框架内置的缓存对象
     * @return
     */
    @Bean
    protected CacheManager shiroCacheManager() {
        return new MemoryConstrainedCacheManager();
    }
}
